/**
 * 版权所有(C)，上海海鼎信息工程股份有限公司，2009，所有权利保留。
 * 
 * 项目名：	rumba-widget2
 * 文件名：	RSimpleCheckBox.java
 * 模块说明：	
 * 修改历史：
 * Feb 4, 2009 - lxm - 创建。
 */
package com.hd123.rumba.gwt.widget2.client.form;

import com.google.gwt.dom.client.Document;
import com.google.gwt.event.dom.client.BlurEvent;
import com.google.gwt.event.dom.client.BlurHandler;
import com.google.gwt.event.dom.client.DomEvent;
import com.google.gwt.event.dom.client.FocusEvent;
import com.google.gwt.event.dom.client.FocusHandler;
import com.google.gwt.event.dom.client.KeyCodes;
import com.google.gwt.event.dom.client.KeyDownEvent;
import com.google.gwt.event.dom.client.KeyDownHandler;
import com.google.gwt.event.dom.client.KeyPressEvent;
import com.google.gwt.event.dom.client.KeyPressHandler;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.ui.FocusWidget;

/**
 * 提供一个最简单的CheckBox，其中只有一个Box，而没有包括对应的标题。
 * <p>
 * 
 * <b>CSS Style Rules</b> <ol type=disc>
 * <li>.rb-SimpleCheckBox { 控件 }</li>
 * <li>.rb-SimpleCheckBox-unchecked { 未选中 }</li>
 * <li>.rb-SimpleCheckBox-unchecked-readonly { 未选中,只读 }</li>
 * <li>.rb-SimpleCheckBox-unchecked-focused { 未选中,获得焦点 }</li>
 * <li>.rb-SimpleCheckBox-unchecked-focused-readonly {
 * 未选中,只读,获得焦点 }</li>
 * <li>.rb-SimpleCheckBox-unchecked-disabled { 未选中,不可用 }</li>
 * <li>.rb-SimpleCheckBox-checked { 选中 }</li>
 * <li>.rb-SimpleCheckBox-checked-readonly { 选中,只读 }</li>
 * <li>.rb-SimpleCheckBox-checked-focused { 选中,获得焦点 }</li>
 * <li>.rb-SimpleCheckBox-checked-focused-readonly { 选中,只读,获得焦点 }
 * </li>
 * <li>.rb-SimpleCheckBox-checked-disabled { 选中,不可用 }</li> </ol>
 * 
 * @author lxm
 * 
 */
public class RSimpleCheckBox extends FocusWidget {

  private static final String STYLENAME_DEFAULT = "rb-SimpleCheckBox";

  /**
   * 创建对象实例。
   */
  public RSimpleCheckBox() {
    super(DOM.createDiv());
    setTabIndex(0);
    sinkEvents(Event.ONCLICK);
    setStyleName(STYLENAME_DEFAULT);
    refresh();

    Handler handler = new Handler();
    addFocusHandler(handler);
    addBlurHandler(handler);
    addKeyDownHandler(handler);
    addKeyPressHandler(handler);
  }

  private boolean checked = false;
  private boolean readOnly = false;
  private boolean focused = false;

  /** 是否被选中。默认为false。 */
  public boolean isChecked() {
    return checked;
  }

  /** 是否被选中。默认为false。 */
  public void setChecked(boolean checked) {
    this.checked = checked;
    refresh();
  }

  /**
   * 设置选中状态。
   * 
   * @param checked
   *          指定是否被选中。
   * @param fireClick
   *          指定是否同时触发onClick事件。
   */
  public void setChecked(boolean checked, boolean fireClick) {
    setChecked(checked);
    if (fireClick)
      fireClick();
  }

  /** 是否只读。默认为false。 */
  public boolean isReadOnly() {
    return readOnly;
  }

  /** 是否只读。默认为false。 */
  public void setReadOnly(boolean readOnly) {
    this.readOnly = readOnly;
    refresh();
  }

  public void setEnabled(boolean enabled) {
    super.setEnabled(enabled);
    refresh();
  }

  public void onBrowserEvent(Event event) {
    switch (DOM.eventGetType(event)) {
    case Event.ONCLICK:
      if (!isEnabled() || readOnly) {
        event.preventDefault();
        return;
      } else {
        checked = !checked;
        refresh();
      }
      break;
    }

    super.onBrowserEvent(event);
  }

  private void setFocused(boolean focused) {
    this.focused = focused;
    refresh();
  }

  private void refresh() {
    StringBuffer sb = new StringBuffer();
    sb.append(getStylePrimaryName());
    sb.append(" ");
    sb.append(getStylePrimaryName());
    sb.append(checked ? "-checked" : "-unchecked");
    if (isEnabled()) {
      if (focused)
        sb.append("-focused");
      if (readOnly)
        sb.append("-readonly");
    } else {
      sb.append("-disabled");
    }
    setStyleName(sb.toString());
  }

  /**
   * 触发click事件
   * 
   */
  private void fireClick() {
    DomEvent.fireNativeEvent(Document.get().createClickEvent(0, 0, 0, 0, 0, false, false, false,
        false), this);
  }

  private class Handler implements FocusHandler, BlurHandler, KeyDownHandler, KeyPressHandler {

    public void onFocus(FocusEvent event) {
      setFocused(true);
    }

    public void onBlur(BlurEvent event) {
      setFocused(false);
    }

    @SuppressWarnings("deprecation")
    public void onKeyDown(KeyDownEvent event) {
      int keyCode = event.getNativeKeyCode();
      if (keyCode == '\r' || keyCode == KeyCodes.KEY_ENTER)
        DOM.eventSetKeyCode((Event) event.getNativeEvent(), (char) KeyCodes.KEY_TAB);
    }

    public void onKeyPress(KeyPressEvent event) {
      char charCode = event.getCharCode();
      if (charCode == ' ' && isEnabled() && !readOnly) {
        checked = !checked;
        refresh();
        fireClick();
      }
    }
  }

}
